<?php

/**
 * Swoole Tcp Server here
 */
namespace App\Service\TcpServer;

use Hyperf\Contract\OnReceiveInterface;
use App\Service\Code\Normal;
use App\Model\PssLogModel\RpcMicroServiceLog;
use App\Service\BaseService;

class TcpServer implements OnReceiveInterface
{
    const SEND_BUFFER_LENGTH = 1024;
    const DELIMITER_REPLACE = "{{______\r\n\r\n______}}";//TCP 包体结束分隔符号
    protected $interface_code;
    public function onReceive($server, int $fd, int $fromId, string $body): void
    {
        $start  = microtime(true);
        $result = $this->runTcpService($body);
        //获取客户端请求信息
        $clientInfo     = $server->getClientInfo($fd);
        $remote_ip      = $clientInfo['remote_ip']??'0.0.0.0';
        $server_port    = $clientInfo['server_port']??'0.0.0.0';
        
        //只记录错误日志
        if( $result['code'] != Normal::SUC ) {
            RpcMicroServiceLog::instance()->addLog([
                'interface_code'    => $this->interface_code,
                'request_url'       => $remote_ip . ':' . $server_port ,
                'request_param'     => $body,
                'response_code'     => $result['code'] ?? 0 ,
                'response_data'     => json_encode($result,JSON_UNESCAPED_UNICODE),
                'req_used_time'     => bcsub(microtime(true), $start,3),
            ]);
        }
        
        //请求唯一标识
        $cacheKey   = "mbpps_rpc_socket_{$result['data']['request_id']}_{$fd}";
        unset($result['data']['request_id']);
        $json       = json_encode($result);
        $redis      = BaseService::instance()->getRedisObj();
        $redis->Hset("rpc_socket",$cacheKey,$json);
        $response   = Normal::returnCode($result['code'],$result['msg'],[
            'cacheKey'  => $cacheKey
        ]);
        $server->send($fd,json_encode($response,JSON_UNESCAPED_UNICODE).self::DELIMITER_REPLACE);
    }
    
    /**
     * 开始处理服务业务逻辑
     * @param string $body
     */
    public function runTcpService( string $body = null )
    {
        //反序列化数据
        $data = @json_decode($body,true);
        //异常处理
        try {
            $interface_code         = $data['method'];
            $requestMethodsModule   = \explode(".",$interface_code);
        
            $this->interface_code = $interface_code;
            
            //验证签名和密码
            $res = TcpAuthorationService::instance()->checkRpcClientParametersAuthToken($data, $data['token']);
            if( $res['code'] != Normal::SUC ) {
                return $res;
            }
            
            //解析模块容器
            $service = $requestMethodsModule[0];
            $class   = $requestMethodsModule[1];
            $method  = $requestMethodsModule[2];
        
            //解析数据
            $message        = $data['argments'];
            $classService   = "App\\Service\\{$service}\\{$class}";
            $object         = container()->get($classService);
            $res = $object->{$method}($message);
            $res['data']['request_id'] = $data['request_id'];
            return $res;
        } catch ( \Throwable $t ) {
            return Normal::returnCode(500,"system happened error!",[
                'errorMessage'  => $t->getMessage(),
                'errorFile'     => $t->getFile(),
                'errorLine'     => $t->getLine(),
                'request_id'    => $data['request_id']
            ]);
        }
    }
}